package edu.ilstu.mind.ise.ccp;

import java.io.File;
import java.io.FileReader;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import org.yaml.snakeyaml.Yaml;

import edu.ilstu.mind.ise.ccp.config.YamlObjectInstantiator;
import edu.ilstu.mind.ise.ccp.logger.LoggerFactory;
import edu.ilstu.mind.ise.ccp.mindmodule.MindModule;
import edu.ilstu.mind.ise.ccp.module.Module;

public class CentralControlProcessorRunner {

	public static final String KEY_CLASS = "class";
	public static final String KEY_PROPERTIES = "properties";

	public static final String CCP = "CCP";
	public static final String MIND_MODULE = "MIND_MODULE";

	/**
	 * Entry point into the application. Parses YAML-formatted config files and
	 * runs the CCP.
	 * 
	 * @param args
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception {
		String ccpConfigPath = System.getProperty("ccp.config.path");
		//TODO error and exit if ccpConfigPath is null
		System.out.println("Loading CCP config from: " + ccpConfigPath);
		File cfgFile = new File(ccpConfigPath);
		System.out.println("Absolute CCP config path: " + cfgFile.getAbsolutePath());
		//TODO error and exit if ccpConfigPath does not exist
		Yaml yaml = new Yaml();
		Map<String, Object> cfgMap = (Map<String, Object>) yaml.load(new FileReader(cfgFile));

		LoggerFactory loggerFactory = (LoggerFactory) instantiate(cfgMap, "loggerFactory");

		System.out.println("Creating CCP");
		CentralControlProcessor ccp = (CentralControlProcessor) instantiate(cfgMap, "ccp");
		ccp.setLogger(loggerFactory.createLogger(CCP));

		System.out.println("Creating Mind Module");
		MindModule mindModule = (MindModule) instantiate(cfgMap, "mindModule");
		mindModule.setLogger(loggerFactory.createLogger(MIND_MODULE));
		ccp.setMindModule(mindModule);

		System.out.println("Creating Modules");
		Map<String, Object> modulesCfgMap = (Map<String, Object>) cfgMap.get("modules");
		for (Map.Entry<String, Object> entry : modulesCfgMap.entrySet()) {
			String moduleName = entry.getKey();
			System.out.println("Creating Module <" + moduleName + ">");
			Module module = (Module) instantiate((Map<String, Object>) entry.getValue(), moduleName);
			module.setLogger(loggerFactory.createLogger(moduleName));
			ccp.addModule(moduleName, module);
		}

		ccp.init();
	}

	@SuppressWarnings("unchecked")
	private static Object instantiate(Map<String, Object> cfgMap, String name) throws NoSuchMethodException, ClassNotFoundException,
			InstantiationException, IllegalAccessException, InvocationTargetException {
		Map<String, Object> objectCfg = (Map<String, Object>) cfgMap.get(name);
		String className = (String) objectCfg.get(KEY_CLASS);
		Map<String, Object> props = (Map<String, Object>) objectCfg.get(KEY_PROPERTIES);
		return YamlObjectInstantiator.instantiateObject(className, props);
	}

}
